/**
 * @class 绘制数据代理
 * @author DuskyHuang 圣子
 * @description 提供指示绘制相关数据和管理。
*/

import { Color } from 'cc';
import { Proxy, decorators } from 'cfw';
import { UI, View } from 'notifications';
const { singleton } = decorators;

@singleton
export class GizmosProxy extends Proxy {

    declare public static readonly instance: GizmosProxy;
    private constructor() { super(); }

    // 指示相关
    public get showGrids(): boolean { return this._show_grids; }            // 显示网格（渐变、无限缩放的等距网格等）
    public get showRulers(): boolean { return this._show_rulers; }          // 显示尺度（公里、天文单位、光年刻度圈等）
    public get showTracks(): boolean { return this._show_tracks; }          // 显示星轨（行星、卫星、彗星、太阳系轨迹）
    public get showScopes(): boolean { return this._show_scopes; }          // 显示范围（太阳系、银河系、星系群范围等）
    public get showStructs(): boolean { return this._show_structs; }        // 显示结构（转轴、旋臂、星系群、星系团等）
    public get showLines(): boolean { return this._show_lines; }            // 显示引线（恒星、星云、星团、星系等）
    public get showTarget(): boolean { return this._show_target; }          // 显示目标（靶圈、距离等）

    // 坐标类型
    public get showEquatorial(): boolean { return this._show_celestial && this._use_equatorial; }   // 天球坐标系
    public get showHourAngle(): boolean { return this._show_celestial && !this._use_equatorial; }   // 时角坐标系
    public get showEcliptic(): boolean { return this._show_ecliptic; }     // 黄道坐标系
    public get showGalactic(): boolean { return this._show_galactic; }     // 银道坐标系
    public get showHorizontal(): boolean { return this._show_horizontal; } // 地平坐标系

    // 坐标细节
    public get showCoordGrids(): boolean { return this._coord_grids; }      // 坐标网格
    public get showCoordEquator(): boolean { return this._coord_equator; }  // 天赤道/黄道/银道/地平线
    public get showCoordAxis(): boolean { return this._coord_axis; }        // 天轴/黄轴/银轴
    public get showCoordPolar(): boolean { return this._coord_polar; }      // 天/黄道/银道南北极/天顶
    public get lineStrength(): num.ratio { return this._line_strength; }    // 网格和道线强度

    public getStateByName(name: string): boolean {
        switch (name) {
            case '网格': return this.showGrids;
            case '尺度': return this.showRulers;
            case '星轨': return this.showTracks;
            case '范围': return this.showScopes;
            case '结构': return this.showStructs;
            case '引线': return this.showLines;
            case '目标': return this.showTarget;
            case '天球': return this.showEquatorial;
            case '时角': return this.showHourAngle;
            case '黄道': return this.showEcliptic;
            case '银道': return this.showGalactic;
            case '地平': return this.showHorizontal;
            case '道线': return this.showCoordEquator;
            case '轴线': return this.showCoordAxis;
            case '极点': return this.showCoordPolar;
            default: return false;
        }
    }

    // 网格颜色
    public static readonly GridsColor = {
        SATELLITE: new Color(127, 127, 127, 191),   // 卫星系统
        PLANETARY: new Color(0, 255, 127, 191),     // 行星系统
        SOLAR: new Color(255, 127, 0, 191),         // 恒星系统
        GALACTIC: new Color(0, 255, 255, 191),      // 星际系统
    }

    // 轨道颜色
    public static readonly TrackColors = {
        PLANET: new Color(0, 255, 127, 127),        // 行星轨迹
        SATELLITE: new Color(191, 191, 191, 127),   // 卫星轨迹
        DWARF: new Color(191, 127, 63, 191),        // 矮行星轨迹
        MINOR: new Color(127, 127, 127, 191),       // 小行星轨迹
        COMET: new Color(191, 127, 255, 191),       // 彗星轨迹
        SOLAR: new Color(255, 255, 0, 191),         // 太阳系轨迹
    }

    // 线条颜色
    public static readonly LineColor = {
        KILO_MT_DK: new Color(0, 127, 255, 127),    // 公里数圈（卫星）
        KILO_METER: new Color(63, 153, 153, 127),   // 公里数圈（行星）
        ASTRO_UNIT: new Color(255, 127, 127, 127),  // 天文单位圈
        LIGHT_YEAR: new Color(255, 255, 127, 127),  // 光年圈
        CONST_LINES: new Color(0, 191, 255, 255),   // 星座连线
        EQUATORIAL: new Color(63, 63, 255, 191),    // 天赤道
        ECLIPTIC: new Color(255, 63, 0, 191),       // 黄道线
        GALACTIC: new Color(0, 255, 255, 191),      // 银道线
        HORIZONTAL: new Color(0, 255, 127, 191),    // 地平线
        STARS: new Color(0, 255, 255, 127),         // 恒星指示线（Level1）
        IND_TARGET: new Color(255, 32, 32, 255),  // 目标指示线
        IND_SOLAR: new Color(255, 191, 0, 255),     // 太阳系指示线
        CLUSTER: new Color(158, 158, 255, 111),     // 星团指示线
        NEBULA: new Color(255, 127, 255, 111),      // 星云指示线
        COMPANION: new Color(127, 127, 127, 191),   // 陪伴群星系指示线（都是矮星系）
        LocalGG: new Color(159, 255, 159, 127),     // 本星系群
        VirgoSC: new Color(255, 159, 255, 127),     // 室女座超星系团
        Laniakea: new Color(255, 191, 159, 127),    // 拉尼亚凯亚超星系团
        Observable: new Color(159, 159, 255, 127),  // 可观测宇宙
        LOCAL_AXIS: new Color(255, 255, 0, 255),    // 地轴和箭头 
        LOCAL_DIAM: new Color(255, 255, 255, 255),  // 天体直径
    }

    public static readonly TrackAtt: attenuation = [0.01, 0.05, 20, 30];

    // 坐标颜色
    public static readonly CoordColor = {
        CELESTIAL: new Color(127, 127, 255, 127),   // 天球坐标
        ECLIPTIC: new Color(255, 127, 0, 127),      // 黄道坐标
        GALACTIC: new Color(0, 255, 255, 127),      // 银道坐标
        HORIZONTAL: new Color(0, 255, 127, 127),    // 地平坐标
    }

    // 忽略绘制尺度
    public static readonly RULER_IGNORES: pow10[] = [-7, 11];

    // 尺度颜色
    public static readonly ScopeColor: Partial<Record<scalar, Color>> = {
        Solar: new Color(255, 255, 0, 255),         // 狭义太阳系
        Helio: new Color(255, 127, 0, 255),         // 广义太阳系
        MilkyWay: new Color(63, 255, 255, 255),     // 银河系
        LocalGG: new Color(63, 255, 63, 255),       // 本星系群
        VirgoSC: new Color(255, 63, 255, 255),      // 室女座超星系团
        Laniakea: new Color(255, 127, 63, 255),     // 拉尼亚凯亚超星系团
        Observable: new Color(63, 63, 255, 255),    // 可观测宇宙
    }

    // 区域线淡入淡出范围
    // public static readonly ScopeAtt: attenuation = [0.17, 0.3, 3.5, 7];
    public static readonly ScopeAtt: attenuation = [0.17, 0.3, 0.8, 1];

    // 绘制线条分段数
    public static readonly Segments = {
        CIRCLE: 128,                                // 圆环段数
        ELLIPSE: 256,                               // 椭圆段数
        CYLINDER: 32,                               // 圆柱段数
        LINE: 8,                                    // 渐线段数
        ARC: 64,                                    // 圆弧段数
    }

    protected init(): void {

        this.on(Gizmos.GRIDS, (arg: boolean) => this._show_grids = arg);
        this.on(Gizmos.RULERS, (arg: boolean) => this._show_rulers = arg);
        this.on(Gizmos.TRACKS, (arg: boolean) => this._show_tracks = arg);
        this.on(Gizmos.SCOPES, (arg: boolean) => this._show_scopes = arg);
        this.on(Gizmos.STRUCTS, (arg: boolean) => this._show_structs = arg);
        this.on(Gizmos.LINES, (arg: boolean) => this._show_lines = arg);
        this.on(Gizmos.TARGET, (arg: boolean) => this._show_target = arg);

        this.on(Coord.EQUATORIAL, (arg: boolean) => { this._show_celestial = arg; this._use_equatorial = true; });
        this.on(Coord.HOUR_ANGLE, (arg: boolean) => { this._show_celestial = arg; this._use_equatorial = false; });
        this.on(Coord.ECLIPTIC, (arg: boolean) => this._show_ecliptic = arg);
        this.on(Coord.GALACTIC, (arg: boolean) => this._show_galactic = arg);
        this.on(Coord.HORIZONTAL, (arg: boolean) => this._show_horizontal = arg);
        this.on(Coord.EQUATOR, (arg: boolean) => { this._coord_equator = arg; this._coord_grids = !arg; });
        this.on(Coord.AXIS, (arg: boolean) => this._coord_axis = arg);
        this.on(Coord.POLAR, (arg: boolean) => this._coord_polar = arg);
        this.on(Coord.STRENGTH, (deg: num.rad) => this._line_strength = deg * 2);
    }

    private _show_grids: boolean = true;
    private _show_rulers: boolean = true;
    private _show_tracks: boolean = true;
    private _show_scopes: boolean = true;
    private _show_structs: boolean = true;
    private _show_lines: boolean = true;
    private _show_target: boolean = true;

    private _show_celestial: boolean = false;
    private _use_equatorial: boolean = false;
    private _show_ecliptic: boolean = false;
    private _show_galactic: boolean = false;
    private _show_horizontal: boolean = false;

    private _coord_grids: boolean = true;
    private _coord_equator = false;
    private _coord_axis: boolean = true;
    private _coord_polar: boolean = true;
    private _line_strength: num.ratio = 1;
}

const { Gizmos, Coord } = UI;
export const gizmos = GizmosProxy.instance;